<template>
    <webrtc-viewer ref="webrtcViewerRef" :offer-api="whepStreamUrl" :stop-api="stopApi" header-visibility="always"
        footer-visibility="always" :poster="viewportFallbackSplash" class="w-full h-full" @played="resetColor">
        <div slot="header" class="flex justify-between">
            <span v-if="cameraId">
                相机名称：{{ cameraName }}（IP：{{ cameraId }}）
            </span>
            <div v-if="cameraId">
                <el-button type="primary" round size="small" :title="$t('相机画面.功能.按钮.检测结果、相机ROI')"
                    @click="showOsdDialog = true">
                    {{ $t("相机画面.功能.按钮.图层") }}
                </el-button>
            </div>
        </div>
        <div slot="videoScreen" ref="videoScreenRef" class="w-full h-full">
            <OSDInferenceOverlay :width="videoScreenRect.width.value" :height="videoScreenRect.height.value"
                :cameraId="cameraId" :currentTopics="selectedOsdLayers" :currentRois="currentRois" />
            <section class="pointer-events-auto" style="--el-overlay-color-lighter: transparent">
                <el-dialog v-model="showOsdDialog" :title="$t('相机画面.功能.画面OSD层选项')" draggable center width="30%"
                    class="min-w-180 osd-dialog" style="background-color: #141414 !important;">
                    <fieldset class="osd-fieldset">
                        <legend class="osd-legend">{{ $t("相机画面.功能.检测结果") }}</legend>
                        <el-checkbox-group v-model="selectedOsdLayers" class="osd-checkbox-group">
                            <el-checkbox v-for="item in osdLayerOptions" :key="item.value" :label="item.value"
                                @change="selectedOsdLayersChange($event, item)">
                                {{ $t(item.labelWithI18n) }}
                            </el-checkbox>
                        </el-checkbox-group>
                    </fieldset>
                    <fieldset class="osd-fieldset">
                        <legend class="osd-legend">{{ $t("相机画面.功能.相机属性ROI") }}</legend>
                        <el-form :model="roiFilterModel" class="osd-filter-form">
                            <el-input v-model="roiFilterModel.label" size="small" :placeholder="$t('相机画面.功能.筛选.名称')"
                                class="flex-1" />
                            <el-radio-group v-model="roiFilterModel.stage" size="small">
                                <el-radio-button v-for="(item, index) in roiFilter_optionsOfStage" :key="index"
                                    :label="item.value">
                                    {{ $t(item.label) }}
                                </el-radio-button>
                            </el-radio-group>
                            <el-radio-group v-model="roiFilterModel.positive" size="small">
                                <el-radio-button v-for="(item, index) in roiFilter_optionsOfPositive" :key="index"
                                    :label="item.value">
                                    {{ $t(item.label) }}
                                </el-radio-button>
                            </el-radio-group>
                            <el-button type="info" round size="small" @click="resetRoiFilterModel">
                                {{ $t("相机画面.功能.重置筛选") }}
                            </el-button>
                        </el-form>

                        <el-divider border-style="dashed" class="!my-4" />

                        <div v-if="filteredRoiOptions.length" class="flex flex-wrap gap-2">
                            <el-check-tag v-for="item in filteredRoiOptions" :key="item.value"
                                :checked="checkedRois.includes(item.value)" type="success"
                                @change="checkedRoisChange($event, item)">
                                {{ item.label }}
                            </el-check-tag>
                        </div>
                        <el-empty v-else :image-size="40" />
                    </fieldset>
                </el-dialog>
            </section>
        </div>
    </webrtc-viewer>
</template>

<script setup lang="ts">
defineOptions({
    name: "CameraScreen",
    inheritAttrs: false,
});

import { ref, watch, onMounted, onBeforeUnmount, type PropType } from "vue";
import { useElementBounding } from "@vueuse/core";
import type { CheckboxValueType } from "element-plus";
import type { LayerConfig } from "@/components/CameraOsd/type";

import { isNumber } from "lodash-es";
import { useInferenceResultStoreHook } from "@/vue-stores-pinia/modules/inference-result";
import useOsdDialog, {
    osdLayerOptions,
    roiFilter_optionsOfStage,
    roiFilter_optionsOfPositive,
} from "@/components/compositions/useOsdDialog";

import {
    getSingleCamera_RtspFullUri,
} from "@/data-services/api/index";

import viewportFallbackSplash from "@/assets/images/viewport-fallback-splash.jpg";

import appEnvironment from "@/app-environments";
const {
    networkHosts: {
        apiServer1: { fullHost },
    },
} = appEnvironment;

const stopApi = `/whep`;
const props = defineProps({
    cameraId: {
        type: String,
        default: "",
    },
    online: {
        type: Boolean,
        default: true,
    },
    cameraName: {
        type: String,
        default: "",
    },
    osdList: {
        type: Array as PropType<LayerConfig[]>,
        default: () => [],
    },
});

const inferenceResultStore = useInferenceResultStoreHook();

const webrtcViewerRef = ref<any | null>(null);
const videoScreenRef = ref<HTMLElement | null>(null);
const videoScreenRect = useElementBounding(videoScreenRef);
const whepStreamUrl = ref<string>();

const {
    showOsdDialog,
    selectedOsdLayers,
    roiFilterModel,
    resetRoiFilterModel,
    checkedRois,
    checkedRoisChange,
    currentRois,
    filteredRoiOptions,
    getCameraPropertyRoiOptions,
} = useOsdDialog({
    cameraId: props.cameraId,
});

function selectedOsdLayersChange(value: CheckboxValueType, item: { value: string }) {
    if (value) {
        inferenceResultStore.addTopicUsage(item.value, props.cameraId);
    } else {
        inferenceResultStore.removeTopicUsage(item.value, props.cameraId);
    }
}

function resetColor() {
    webrtcViewerRef.value?.style.setProperty(
        "--webrtc-viewer-status-color",
        "var(--el-color-primary)"
    );
    webrtcViewerRef.value?.hideError();
}

watch(
    [videoScreenRect.width, videoScreenRect.height],
    ([width, height]) => {
        if (isNumber(width) && isNumber(height)) {
            // 更新每个 camera 的最新矩形大小
            inferenceResultStore.updateCameraRectByCameraId(props.cameraId, { width, height });
        }
    },
    { immediate: true }
);

watch(
    () => props.cameraId,
    (val) => {
        if (!val) return;

        getSingleCamera_RtspFullUri(val).then(([streamUrl]) => {
            if (streamUrl) {
                whepStreamUrl.value = `${fullHost}/whep/endpoint/${streamUrl}`;
                getCameraPropertyRoiOptions(val); // 获取相机属性ROI配置
            } else {
                whepStreamUrl.value = "";
                webrtcViewerRef.value?.style.setProperty(
                    "--webrtc-viewer-status-color",
                    "var(--el-color-info)"
                );
            }
        });
    },
    { immediate: true }
);

onMounted(() => {
    watch(
        () => props.online,
        (val) => {
            if (val) {
                webrtcViewerRef.value?.style.setProperty(
                    "--webrtc-viewer-status-color",
                    "var(--el-color-primary)"
                );
                webrtcViewerRef.value?.hideError();
            } else {
                webrtcViewerRef.value?.style.setProperty(
                    "--webrtc-viewer-status-color",
                    "var(--el-color-info)"
                );
                // webrtcViewerRef.value?.showError();
            }
        },
        { immediate: true }
    );

    selectedOsdLayers.value.forEach((topic) => {
        inferenceResultStore.addTopicUsage(topic, props.cameraId);
    });
});

onBeforeUnmount(() => {
    selectedOsdLayers.value.forEach((topic) => {
        inferenceResultStore.removeTopicUsage(topic, props.cameraId);
    });
});
</script>

<style scoped lang="scss">
.osd-dialog :deep(.el-dialog__body) {
    display: flex;
    flex-direction: column;
    gap: 1.5rem;
    padding: 0.5rem;
}

/* Fieldset样式 */
.osd-fieldset {
    border: 1px solid #4a4a4a;
    border-radius: 0.375rem;
    padding: 1rem;
    margin: 0;

    .el-form {
        .el-input {
            font-size: 16px;
        }
    }
}

.osd-legend {
    padding: 0 0.5rem;
    font-weight: 600;
    font-size: 0.9rem;
    color: #cfd3dc;
}

/* Checkbox组样式 */
.osd-checkbox-group {
    display: flex;
    gap: 0.75rem;
}

.osd-checkbox-group :deep(.el-checkbox) {
    margin-right: 0;
    height: auto;
}

/* 筛选表单样式 */
.osd-filter-form {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
}

.osd-filter-form :deep(.el-input) {
    min-width: 120px;
}

.osd-filter-form :deep(.el-radio-group) {
    flex-shrink: 0;
}

.el-dialog__body {
    color: #cfd3dc
}
</style>
